local addon, ns = ...
local cfg = ns.cfg
local tags = ns.tags

local playerClass = select(2, UnitClass("player"))	
local blankTex = "Interface\\Buttons\\WHITE8x8"
local backdrop = {bgFile = blankTex, edgeFile = blankTex, edgeSize = 1, insets = { left = -1, right = -1, top = -1, bottom = -1}}

-- change some colors
local colors = setmetatable({
	power = setmetatable({
	["MANA"] = {1.00, 1.00, 1.00},
	["RAGE"] = {1.00, 1.00, 1.00},
	["FUEL"] = {1.00, 1.00, 1.00},
	["FOCUS"] = {1.00, 1.00, 1.00},
	["ENERGY"] = {1.00, 1.00, 1.00},
	["AMMOSLOT"] = {0.8, 0.6, 0},
	["RUNIC_POWER"] = {1.00, 1.00, 1.00},
	["POWER_TYPE_STEAM"] = {0.55, 0.57, 0.61},
	["POWER_TYPE_PYRITE"] = {0.60, 0.09, 0.17},
	["HOLY_POWER"] = {0.95, 0.93, 0.15},	
	["SOUL_SHARDS"] = {0.5, 0.0, 0.56},
	}, {__index = oUF.colors.power}),
}, {__index = oUF.colors})

-- format numbers
function round(num, idp)
  if idp and idp > 0 then
    local mult = 10^idp
    return math.floor(num * mult + 0.5) / mult
  end
  return math.floor(num + 0.5)
end

function CoolNumber(num)
	if(num >= 1e6) then
		return round(num/1e6,cfg.Numberzzz).."m"
	elseif(num >= 1e3) then
		return round(num/1e3,cfg.Numberzzz).."k"
	else
		return num
	end
end

-- health update
local PostUpdateHealth = function(Health, unit, min, max)
	local self = Health:GetParent()
    local d =(round(min/max, 2)*100)
	local c = UnitClassification(unit)
	
	if(UnitIsDead(unit)) then
		Health:SetValue(0)
		Health.value:SetText"RIP"			
	elseif(UnitIsGhost(unit)) then
		Health:SetValue(0)
		Health.value:SetText"GHO"			
	elseif(not UnitIsConnected(unit)) then	
		Health.value:SetText"OFF"	
	elseif(UnitIsTapped(unit) and not UnitIsTappedByPlayer(unit)) then
		Health.value:SetText("TAP")		
	else
		Health.value:SetText(CoolNumber(min))	
		Health:SetStatusBarColor(unpack(cfg.maincolor))		
	end

	-- set health background color
	if not cfg.solidHPBGcolor then
		local color = RAID_CLASS_COLORS[select(2, UnitClass(unit))]	
		if UnitIsPlayer(unit) and color then
			self.Health.bg:SetVertexColor(color.r, color.g, color.b, 0.8)
		else
			local r, g, b = UnitSelectionColor(unit)
			self.Health.bg:SetVertexColor(r, g, b, 0.8)	
		end
		
		if UnitLevel(unit) == 0 then
			self.Health.bg:SetVertexColor(0, 0, 0, 0.5)
		elseif UnitIsConnected(unit) ~= 1 then
			self.Health.bg:SetVertexColor(0, 0, 0, 0.5)
		elseif UnitIsDeadOrGhost(unit) == 1 then
			self.Health.bg:SetVertexColor(200/255, 20/255, 40/255, 0.5)
		end
	else
		if UnitIsDeadOrGhost(unit) == 1 then
			self.Health.bg:SetVertexColor(200/255, 20/255, 40/255, 0.5)
		else
			hpBGr, hpBGg, hpBGb = unpack(cfg.hpBGcolor)
			self.Health.bg:SetVertexColor(hpBGr, hpBGg, hpBGb, 1)
		end
	end		
	-- set text color
	if(unit) then
		if(d < 25) then
			Health.value:SetTextColor(200/255, 20/255, 40/255)
		else
			Health.value:SetTextColor(unpack(cfg.sndcolor))
		end
	end	
end

-- power update
local PostUpdatePower = function(Power, unit, min, max)
	local dp =(round(min/max, 2)*100)
	
	if(min == 0 or max == 0 or not UnitIsConnected(unit)) then
		Power.value:SetText()
		Power:SetValue(0)
	elseif(UnitIsDead(unit) or UnitIsGhost(unit)) then
		Power:SetValue(0)
		Power.value:SetText()
	elseif(unit == "player") then
		if(dp < 100) then
			Power.value:Show()
			Power.value:SetText(CoolNumber(min))
		else
			Power.value:Hide()
		end	
	else
		Power.value:SetText(CoolNumber(min))
	end
	
	-- color power text by power type
	local _, ptype = UnitPowerType(unit)
        if(colors.power[ptype]) then
		r, g, b = unpack(colors.power[ptype])
	end
	
	Power.value:SetTextColor(r, g, b)
end

local PostUpdatePowerRaid = function(Power, unit)
	local powertype, _ = UnitPowerType(unit)
	if powertype ~= SPELL_POWER_MANA then
		Power:Hide()
	else
		Power:Show()
	end	
end	
	
-- custom castbar text (curCastTime/maxCastTime)
local function CustomTimeText(self, duration)
	if self.casting then
		self.Time:SetFormattedText('%.1f /', (self.max - duration))
		self.Time2:SetFormattedText(' %.1f', self.max)
	elseif self.channeling then
		self.Time:SetFormattedText('%.1f /', duration)
		self.Time2:SetFormattedText(' %.1f', self.max)
	end
end

--------------------
-- aura functions --
--------------------

-- format time
local FormatTime = function(s)
	local day, hour, minute = 86400, 3600, 60
	if s >= day then
		return format("%dd", floor(s/day + 0.5)), s % day
	elseif s >= hour then
		return format("%dh", floor(s/hour + 0.5)), s % hour
	elseif s >= minute then
		if s <= minute * 5 then
			return format('%d:%02d', floor(s/60), s % minute), s - floor(s)
		end
		return format("%dm", floor(s/minute + 0.5)), s % minute
	elseif s >= minute / 12 then
		return floor(s + 0.5), (s * 100 - floor(s * 100))/100
	end
	return format("%.1f", s), (s * 100 - floor(s * 100))/100
end


-- aura timer 
local CreateAuraTimer = function(self, elapsed)
		self.elapsed = (self.elapsed or 0) + elapsed
	if self.elapsed >= 0.1 then
		if not self.first then
			self.timeLeft = self.timeLeft - self.elapsed
		else
			self.timeLeft = self.timeLeft - GetTime()
			self.first = false
		end
		if self.timeLeft > 0 then
			local time = FormatTime(self.timeLeft)
			self.time:SetText(time)
			if self.timeLeft < 5 then
				self.time:SetTextColor(1, 0, 0)
			elseif self.timeLeft >= 5 and self.timeLeft < cfg.HideAuraTimer then
				self.time:SetTextColor(unpack(cfg.sndcolor))
			else
				self.time:SetText('')
				self.time:SetTextColor(unpack(cfg.sndcolor))			
			end
			else
				self.time:Hide()
				self:SetScript("OnUpdate", nil)
			end
			self.elapsed = 0
		end
end

-- icon style
local PostCreateIcon = function(Auras, button)
	local buttonwidth = button:GetWidth()
	button.cd.noOCC = true		 		-- hide OmniCC CDs
	button.cd.noCooldownCount = true	-- hide CDC CDs
	Auras.disableCooldown = true		-- hide CD spiral
	Auras.showDebuffType = true			-- show debuff border type color 		
	
	button.overlay:SetTexture(cfg.Auratex)
    button.overlay:SetPoint("TOPLEFT", button.icon, "TOPLEFT", -2, 2)
    button.overlay:SetPoint("BOTTOMRIGHT", button.icon, "BOTTOMRIGHT", 2, -2)		
	button.overlay:SetTexCoord(0, 1, 0, 1)
	button.overlay.Hide = function(self) self:SetVertexColor(unpack(cfg.iconcolor)) end		
	
	button.time = button:CreateFontString(nil, 'OVERLAY')
	button.time:SetFont(cfg.NumbFont, buttonwidth/1.8, cfg.fontFNum)	
	button.time:SetPoint("BOTTOM", button, 0, -2)
	button.time:SetJustifyH('CENTER')
	button.time:SetVertexColor(unpack(cfg.sndcolor))	
		
	local count = button.count
	count:ClearAllPoints()
	count:SetPoint("TOPRIGHT", button, 1, 1)
	count:SetFont(cfg.NumbFont, buttonwidth/2.6, cfg.fontFNum)
	count:SetVertexColor(unpack(cfg.sndcolor))
	
	button.icon:SetTexCoord(.07, .93, .07, .93)
end

-- update icon
local PostUpdateIcon
do
	local playerUnits = {
		player = true,
		pet = true,
		vehicle = true,
	}

	PostUpdateIcon = function(icons, unit, icon, index, offset, filter, isDebuff)
	local name, _, _, _, dtype, duration, expirationTime, unitCaster, _ = UnitAura(unit, index, icon.filter)
	local texture = icon.icon
	
	if unit == "target" or unit == "focus" then
		if duration and duration > 0 then
			icon.time:Show()
			icon.timeLeft = expirationTime
			icon:SetScript("OnUpdate", CreateAuraTimer)
		else
			icon.time:Hide()
		end
	else
		if duration and duration > 0 then
			icon.time:Show()
			icon.timeLeft = expirationTime
			icon:SetScript("OnUpdate", CreateAuraTimer)
		else
			icon.time:Hide()
		end
	end

	if unit == "target" or unit == "focus" then
		if (playerUnits[icon.owner]) then
			local color = DebuffTypeColor[dtype] or DebuffTypeColor.none
			icon.overlay:SetVertexColor(unpack(cfg.iconcolor))			
			texture:SetDesaturated(false)	
		else
			icons.showDebuffType = false
			icon.overlay:SetVertexColor(unpack(cfg.iconcolor))	
			texture:SetDesaturated(true)
		end	
	end	
	
	icon.first = true
	end
end

-- right click menu
local dropdown = CreateFrame("Frame", "MyAddOnUnitDropDownMenu", UIParent, "UIDropDownMenuTemplate")
UIDropDownMenu_Initialize(dropdown, function(self)
	local unit = self:GetParent().unit
	if not unit then return end

	local menu, name, id
	if UnitIsUnit(unit, "player") then
		menu = "SELF"
	elseif UnitIsUnit(unit, "vehicle") then
		menu = "VEHICLE"
	elseif UnitIsUnit(unit, "pet") then
		menu = "PET"
	elseif UnitIsPlayer(unit) then
		id = UnitInRaid(unit)
		if id then
			menu = "RAID_PLAYER"
			name = GetRaidRosterInfo(id)
		elseif UnitInParty(unit) then
			menu = "PARTY"
		else
			menu = "PLAYER"
		end
	else
		menu = "TARGET"
		name = RAID_TARGET_ICON
	end
	if menu then
		UnitPopup_ShowMenu(self, menu, unit, name, id)
	end
end, "MENU")

local menu = function(self)
	dropdown:SetParent(self)
	ToggleDropDownMenu(1, nil, dropdown, "cursor", 0, 0)
end

-- threat highlight
local function updateThreatStatus(self, event, u)
	if (self.unit ~= u) then return end
	local s = UnitThreatSituation(u)
	if s and s > 1 then
		local r, g, b = GetThreatStatusColor(s)
		self.ThreatHlt:Show()
		self.ThreatHlt:SetVertexColor(r, g, b, 0.5)
	else
		self.ThreatHlt:Hide()
	end
end

-- debuff highlight
local CanDispel = {
	PRIEST = { Magic = true, Disease = true, },
	SHAMAN = { Curse = true},
	PALADIN = { Poison = true, Disease = true, },
	MAGE = { Curse = true, },
	DRUID = { Curse = true, Poison = true},
}
local dispellist = CanDispel[playerClass] or {}

local function GetDebuffType(unit)
	if not UnitCanAssist("player", unit) then return nil end
	local i = 1
	while true do
		local name, rank, texture, count, debufftype, duration, expirationTime, source = UnitDebuff(unit, i)
		if not texture then break end
		if debufftype and dispellist[debufftype] then
			return debufftype
		end
		i = i + 1
	end
end

local function updateDispel(self, event, u)
	if not u or self.unit ~= u then return end
	local debufftype = GetDebuffType(u)
	if debufftype then
		local color = DebuffTypeColor[debufftype] 
		self.Glow:SetBackdropBorderColor(color.r, color.g, color.b)
	else
		self.Glow:SetBackdropBorderColor(unpack(cfg.brdcolor))
	end
end

-- mouseover highlight
local UnitFrame_OnEnter = function(self)
	UnitFrame_OnEnter(self)
	self.Mouseover:Show()	
end

local UnitFrame_OnLeave = function(self)
	UnitFrame_OnLeave(self)
	self.Mouseover:Hide()
end

--------------------------------
-- shared stuff for all units --
--------------------------------
local Shared = function(self, unit, isSingle)
local playerClass = select(2, UnitClass("player"))	
local unitIsPartyPet = self:GetAttribute("unitsuffix") == "pet"

	self.menu = menu
	self:SetAttribute("*type2", "menu")

	self:SetScript("OnEnter", UnitFrame_OnEnter)
	self:SetScript("OnLeave", UnitFrame_OnLeave)

	self:RegisterForClicks"AnyUp"

	-- set/clear focus with alt + left click
    local ModKey = 'Alt'
    local MouseButton = 1
    local key = ModKey .. '-type' .. (MouseButton or '')
	if(self.unit == 'focus') then
		self:SetAttribute(key, 'macro')
		self:SetAttribute('macrotext', '/clearfocus')
	else
		self:SetAttribute(key, 'focus')
	end
	
	if cfg.HideBlizzardAuras == true then
		-- hide blizzard buff, debuff and weapon enchant frame
		local BlizzFrame = _G['BuffFrame']
		BlizzFrame:UnregisterEvent('UNIT_AURA')
		BlizzFrame:Hide()
		BlizzFrame = _G['TemporaryEnchantFrame']
		BlizzFrame:Hide()
	end
	
	-- hp
	local hp = CreateFrame("StatusBar", nil, self)
	hp:SetStatusBarTexture(cfg.tex)
	hp:SetPoint"TOP"
	hp:SetPoint"LEFT"
	hp:SetPoint"RIGHT"
	hp:SetStatusBarColor(unpack(cfg.maincolor))
	hp:GetStatusBarTexture():SetHorizTile(true)
	
	hp.frequentUpdates = true
	self.Health = hp
	self.Health.PostUpdate = PostUpdateHealth	
	
	-- hp border
	self.Glow = CreateFrame("Frame", nil, hp)
	self.Glow:SetPoint("TOPLEFT", hp, "TOPLEFT", -4, 4)
	self.Glow:SetPoint("BOTTOMRIGHT", hp, "BOTTOMRIGHT", 4, -4)
	self.Glow:SetBackdrop{edgeFile = cfg.glowtex1, edgeSize = cfg.edgesize, insets = {left = cfg.insets, right = cfg.insets, top = cfg.insets, bottom = cfg.insets}}
	self.Glow:SetBackdropColor(0, 0, 0, 0.8)
	self.Glow:SetBackdropBorderColor(unpack(cfg.brdcolor))
	self.Glow:SetFrameLevel(20)	
	
	-- hp bg
	hpbg = hp:CreateTexture(nil, "BACKGROUND")
	hpbg:SetAllPoints(hp)
	hpbg:SetTexture(cfg.tex)
	hp.bg = hpbg
	
	-- pp
	local pp = CreateFrame("StatusBar", nil, self)
	pp:SetWidth(cfg.widthP)			
	pp:SetHeight(cfg.heightPP)
	pp:SetStatusBarTexture(cfg.tex)
	pp:SetPoint("TOPLEFT", self.Health, "BOTTOMLEFT", 0, -cfg.PPyOffset)
	pp:GetStatusBarTexture():SetHorizTile(true)
	
	pp.frequentUpdates = true
	pp.colorClass = true
	pp.colorReaction = true	
	self.Power = pp	
	self.Power.PostUpdate = PostUpdatePower	
	
	-- pp border
	self.Glow.pp = CreateFrame("Frame", nil, pp)
	self.Glow.pp:SetPoint("TOPLEFT", pp, "TOPLEFT", -4, 4)
	self.Glow.pp:SetPoint("BOTTOMRIGHT", pp, "BOTTOMRIGHT", 4, -4)
	self.Glow.pp:SetBackdrop{edgeFile = cfg.glowtex1, edgeSize = cfg.edgesize, insets = {left = cfg.insets, right = cfg.insets, top = cfg.insets, bottom = cfg.insets}}
	self.Glow.pp:SetBackdropColor(0, 0, 0, 0.8)
	self.Glow.pp:SetBackdropBorderColor(unpack(cfg.brdcolor))
	self.Glow.pp:SetFrameLevel(20)		
	
	-- pp bg
	local ppBG = pp:CreateTexture(nil, 'BORDER')
	ppBG:SetAllPoints()	
	ppBG:SetTexture(cfg.tex)
	ppBG:SetAlpha(0.8)	
	ppBG.multiplier = 0.4
	pp.bg = ppBG	
	
	-- enable custom colors
	self.colors = colors

	-- font strings
	self.Health.value = hp:CreateFontString(nil, "OVERLAY")
	self.Health.value:SetFont(cfg.NumbFont, cfg.NumbFS, cfg.fontFNum)
	
	self.Power.value = pp:CreateFontString(nil, "OVERLAY")
	self.Power.value:SetFont(cfg.NumbFont, cfg.NumbFS, cfg.fontFNum)	
	
	self.Name = hp:CreateFontString(nil, "OVERLAY")
	self.Name:SetFont(cfg.NameFont, cfg.NameFS, cfg.FontF)
	self:Tag(self.Name, '[raidcolor][abbrevname]')

	self.Status = hp:CreateFontString(nil, "OVERLAY")
	self.Status:SetFont(cfg.NameFont, cfg.NameFS, cfg.FontF)
	self:Tag(self.Status, '[afkdnd][difficulty][smartlevel]')
	
	-- mouseover highlight
	local mov = self.Health:CreateTexture(nil, "OVERLAY")
	mov:SetAllPoints(self.Health)
	mov:SetTexture("Interface\\AddOns\\oUF_Arp\\media\\mouseover")
	mov:SetVertexColor(1,1,1,.36)
	mov:SetBlendMode("ADD")
	mov:Hide()
	self.Mouseover = mov
	
	-- threat highlight
	local Thrt = self.Health:CreateTexture(nil, "OVERLAY")
	Thrt:SetAllPoints(self.Health)
	Thrt:SetTexture("Interface\\AddOns\\oUF_Arp\\media\\threat")
	--Thrt:SetVertexColor(1,1,1,.36)
	Thrt:SetBlendMode("ADD")
	Thrt:Hide()
	self.ThreatHlt = Thrt	
	
	-- update threat
	self:RegisterEvent("UNIT_THREAT_LIST_UPDATE", updateThreatStatus)
	self:RegisterEvent("UNIT_THREAT_SITUATION_UPDATE", updateThreatStatus)		
end

----------------------
-- object functions --
----------------------	

-- create and update portraits
local Portrait_PostUpdate = function(Portrait, unit)
	if (not UnitExists(unit) or not UnitIsConnected(unit) or not UnitIsVisible(unit)) then
		Portrait:Hide()
	else
		Portrait:Show()
		Portrait:SetCamera(0)
		-- workaround for setting portrait alpha ...
		Portrait:SetAlpha(0)
		Portrait:SetAlpha(cfg.pAlpha)
	end
end

local createPortraits = function(self, unit)
	self.Portrait = CreateFrame("PlayerModel", nil, self.Health)
	self.Portrait:SetAllPoints(self.Health)
end

local createPortraitBGBorder = function(self, unit)
	local PortraitBG = self:CreateTexture(nil, "BACKGROUND")
	PortraitBG:SetTexture(cfg.tex)
	PortraitBG:SetAllPoints(self.Portrait)	
	PortraitBG:SetVertexColor(unpack(cfg.infocolor))		
	PortraitBG:SetAlpha(1)
	
	self.PortraitBorder = CreateFrame("Frame", nil, self)
	self.PortraitBorder:SetPoint("TOPLEFT", self.Portrait, "TOPLEFT", -2, 2)
	self.PortraitBorder:SetPoint("BOTTOMRIGHT", self.Portrait, "BOTTOMRIGHT", 2, -2)	
	self.PortraitBorder:SetBackdrop(backdrop)
	self.PortraitBorder:SetBackdropColor(unpack(cfg.backdropcolor))
	self.PortraitBorder:SetBackdropBorderColor(unpack(cfg.brdcolor))	
	self.PortraitBorder:SetFrameLevel(0)		
end	

-- castbar
local createCastbar = function(self, unit)
	local cb = CreateFrame("StatusBar", nil, self)
	cb:SetStatusBarTexture(cfg.tex)
	cb:SetStatusBarColor(unpack(cfg.maincolor))
	cb:SetFrameLevel(8)

	self.Castbar = cb

	cb.Text = cb:CreateFontString(nil, 'ARTWORK')
	cb.Text:SetJustifyH("LEFT")		
	cb.Text:SetFont(cfg.NameFont, cfg.CastFS, cfg.FontF)
	cb.Text:SetTextColor(unpack(cfg.sndcolor)) 
		
	cb.Time = cb:CreateFontString(nil, 'ARTWORK')
	cb.Time:SetFont(cfg.NumbFont, cfg.CastFS, cfg.fontFNum)
	cb.Time:SetJustifyH('RIGHT')		
	cb.Time:SetTextColor(unpack(cfg.sndcolor))	

	cb.Time2 = cb:CreateFontString(nil, 'ARTWORK')
	cb.Time2:SetFont(cfg.NumbFont, cfg.CastFS, cfg.fontFNum)
	cb.Time2:SetJustifyH('RIGHT')		
	cb.Time2:SetTextColor(unpack(cfg.sndcolor))
	
	cb.CustomTimeText = CustomTimeText	
		
	cb.bg1 = cb:CreateTexture(nil, "BORDER")
	cb.bg1:SetAllPoints(cb)
	cb.bg1:SetTexture(cfg.tex)
	cb.bg1:SetVertexColor(0.2,0.2,0.2,1)	
	
	if cfg.movecb == true then
	cb.Glow = CreateFrame("Frame", nil, cb)
	cb.Glow:SetPoint("TOPLEFT", cb, "TOPLEFT", -3, 3)
	cb.Glow:SetPoint("BOTTOMRIGHT", cb, "BOTTOMRIGHT", 3, -3)
	cb.Glow:SetBackdrop{edgeFile = cfg.glowtex1, edgeSize = cfg.edgesize, insets = {left = cfg.insets, right = cfg.insets, top = cfg.insets, bottom = cfg.insets}}
	cb.Glow:SetBackdropColor(0, 0, 0, 0)
	cb.Glow:SetBackdropBorderColor(unpack(cfg.brdcolor))
	end
end

-- buffs
local createBuffs = function(self)
	local Buffs = CreateFrame("Frame", nil, self)
	Buffs:SetPoint'LEFT'
	Buffs:SetPoint'RIGHT'
	Buffs.num = 40
	Buffs.spacing = 4	

	self.Buffs = Buffs
	
	Buffs.PostCreateIcon = PostCreateIcon
	Buffs.PostUpdateIcon = PostUpdateIcon	
end

-- debuffs
local createDebuffs = function(self)
	local Debuffs = CreateFrame("Frame", nil, self)
	Debuffs:SetPoint'LEFT'
	Debuffs:SetPoint'RIGHT'
	Debuffs.spacing = 4

	self.Debuffs = Debuffs
	
	Debuffs.PostCreateIcon = PostCreateIcon
	Debuffs.PostUpdateIcon = PostUpdateIcon
end

-- phase icon
local createPhaseIcon = function(self)
	local pIcon = self.Health:CreateTexture(nil, 'OVERLAY')
	pIcon:SetSize(18, 18)
	self.PhaseIcon = pIcon
end

-- quest icon
local createQuestIcon = function(self)
	local qIcon = self.Health:CreateTexture(nil, 'OVERLAY')
	qIcon:SetSize(18, 18)
	self.QuestIcon = qIcon
end

-- raid icons
local createRaidIcon = function(self)
	RI = self.Health:CreateTexture(nil, "OVERLAY")
	RI:SetTexture("Interface\\AddOns\\oUF_Arp\\media\\raidicons.blp")
	RI:SetSize(18, 18)
	self.RaidIcon = RI
end
		
-- plugin support
local SpellRange = function(self)
	if IsAddOnLoaded("oUF_SpellRange") then	
		self.SpellRange = {
		insideAlpha = 1,
		outsideAlpha = cfg.FadeOutAlpha}	
	end
end
	
local SmoothUpdate = function(self)
	if IsAddOnLoaded("oUF_Smooth") then
		self.Health.Smooth = true
		self.Power.Smooth = true	
	end	
end
	
local TotemBar = function(self)
	if IsAddOnLoaded("oUF_TotemBar") then
		self.TotemBar = {}
		for i = 1, 4 do
			self.TotemBar[i] = CreateFrame("StatusBar", nil, self)
			self.TotemBar[i]:SetHeight(cfg.ClassBarHeight)
			self.TotemBar[i]:SetWidth(((cfg.widthP - 12)/4))
		if (i == 1) then
			self.TotemBar[i]:SetPoint("TOPLEFT", self.Power, "BOTTOMLEFT", 0, -6)
		else
			self.TotemBar[i]:SetPoint("TOPLEFT", self.TotemBar[i-1], "TOPRIGHT", 4, 0)
		end
			self.TotemBar[i]:SetStatusBarTexture(cfg.tex)
			self.TotemBar[i]:SetMinMaxValues(0, 1)
			self.TotemBar[i].destroy = true			
			
			self.TotemBar[i].bg = self.TotemBar[i]:CreateTexture(nil, "BORDER")
			self.TotemBar[i].bg:SetAllPoints(self.TotemBar[i])
			self.TotemBar[i].bg:SetTexture(cfg.tex)
			self.TotemBar[i].bg.multiplier = 0.4
			self.TotemBar[i].bg:SetAlpha(1.0)

			self.TotemBarBorder = CreateFrame("Frame", nil, self)
			self.TotemBarBorder:SetPoint("TOPLEFT", self.TotemBar[i], "TOPLEFT", -4, 4)
			self.TotemBarBorder:SetPoint("BOTTOMRIGHT", self.TotemBar[i], "BOTTOMRIGHT", 4, -4)				
			self.TotemBarBorder:SetBackdrop{edgeFile = cfg.glowtex1, edgeSize = cfg.edgesize, insets = {left = cfg.insets, right = cfg.insets, top = cfg.insets, bottom = cfg.insets}}
			self.TotemBarBorder:SetBackdropColor(0, 0, 0, 0.8)
			self.TotemBarBorder:SetBackdropBorderColor(unpack(cfg.brdcolor))	
			self.TotemBarBorder:SetFrameLevel(0)		
		end
	end
end

-------------------------
-- unit specific stuff --
-------------------------
local UnitSpecific = {
	player = function(self, ...)
		Shared(self, ...)
		
		if cfg.useCastbar then	
		createCastbar(self)	
		if cfg.movecb == true then
		if cfg.ArpUI and playerClass == "DRUID" or playerClass == "WARRIOR" or playerClass == "PALADIN" or playerClass == "DEATHKNIGHT" or playerClass == "HUNTER" then
		self.Castbar:SetPoint(cfg.anchor, cfg.cbpp, cfg.anchor2, cfg.xposp, cfg.yposp2)
		else
		self.Castbar:SetPoint(cfg.anchor, cfg.cbpp, cfg.anchor2, cfg.xposp, cfg.yposp)
		end
		self.Castbar:SetHeight(cfg.cpheight)
		self.Castbar:SetWidth(cfg.cpwidth)
		else
		self.Castbar:SetAllPoints(self.Health)
		end

			-- disable blizzards pet castbar
			PetCastingBarFrame:UnregisterAllEvents()
			PetCastingBarFrame.Show = function() end
			PetCastingBarFrame:Hide()
			

			self.Castbar.Text:SetPoint("LEFT", self.Castbar, "LEFT", 4, 0)	
			self.Castbar.Time2:SetPoint("RIGHT", self.Castbar, "RIGHT", -2, 0)
			self.Castbar.Time:SetPoint("RIGHT", self.Castbar.Time2, "LEFT", 0, 0)
		end
		
		self.Health.value:SetPoint("RIGHT", self.Health, "RIGHT", -1, 5, cfg.playerHPy)	
		self.Power.value:SetPoint("RIGHT", self.Health, "RIGHT", -4, -12)	
		self.Health.value:SetFont(cfg.NumbFont, cfg.NumbFS1, cfg.fontFNum)
		self.Power.value:SetFont(cfg.NumbFont, cfg.NumbFS2, cfg.fontFNum)	
		
		if cfg.pPervalue then
		self.Health.Text = self.Health:CreateFontString(nil, 'OVERLAY') 
		self.Health.Text:SetFont(cfg.NumbFont, cfg.NameFS, cfg.FontF)
		self.Health.Text.frequentUpdates = FreqUpdate
		self:Tag(self.Health.Text,'[My_PerHP]|r')
		self.Health.Text:SetJustifyH('CENTER')
		self.Health.Text:SetTextColor(unpack(cfg.sndcolor))
		self.Health.Text:SetPoint('LEFT',self.Health, 2, 0)
		end
		
		if playerClass == "DRUID" then
			self.Name:SetPoint("CENTER", self.Health, 0, 0)
			self:Tag(self.Name, '[druidPower]')
		end
		
		self.Health:SetHeight(cfg.heightP)
		self.Health:SetWidth(cfg.widthP)	
		self.Power:SetWidth(cfg.widthP)		

		-- buffs
		if cfg.PlayerBuffsOnPlayerFrame then
			createBuffs(self)
			
				if cfg.useClassBar and playerClass == "WARLOCK" or playerClass == "PALADIN" or playerClass == "DEATHKNIGHT" or cfg.useeclip or IsAddOnLoaded("oUF_TotemBar") then
					self.Buffs:SetPoint("TOP", self.Power, "BOTTOM", 0, -(12 + cfg.ClassBarHeight))
				else
					self.Buffs:SetPoint("TOP", self.Power, "BOTTOM", 0, -6)
				end

		self.Buffs.initialAnchor = "TOPRIGHT"	
		self.Buffs["growth-x"] = "LEFT"		
		self.Buffs["growth-y"] = "DOWN"
		self.Buffs.size = ((cfg.widthP/8)/1.5)
		self.Buffs.num = 8
		end
		
		-- debuffs
		if cfg.PlayerBuffsOnPlayerFrame then
			createDebuffs(self)
			
				if cfg.useClassBar and playerClass == "WARLOCK" or playerClass == "PALADIN" or playerClass == "DEATHKNIGHT" or cfg.useeclip or IsAddOnLoaded("oUF_TotemBar") then
					self.Debuffs:SetPoint("TOP", self.Power, "BOTTOM", 0, -(37 + cfg.ClassBarHeight))
				else
					self.Debuffs:SetPoint("TOP", self.Power, "BOTTOM", 0, -31)
				end

		self.Debuffs.initialAnchor = "TOPRIGHT"
		self.Debuffs["growth-x"] = "LEFT"		
		self.Debuffs["growth-y"] = "DOWN"
		self.Debuffs.size = ((cfg.widthP/8)/1.5)
		self.Debuffs.num = 8
		end
		
		if cfg.usePortrait then		
			createPortraits(self)	
			self.Portrait:SetPoint("TOPLEFT", self, "TOPLEFT", 0, 0)
			self.Portrait.PostUpdate = Portrait_PostUpdate	
		end
			
		-- Icons
		createRaidIcon(self)
		self.RaidIcon:SetPoint("CENTER", self.Health, "CENTER", 0, 0)
		
		if cfg.pPervalue then
		RIc = self.Health:CreateTexture(nil, 'OVERLAY')
		RIc:SetSize(12, 12)	
		RIc:SetPoint("LEFT", self.Health, "LEFT", 55, 0)
		self.Resting = RIc
		else
		RIc = self.Health:CreateTexture(nil, 'OVERLAY')
		RIc:SetSize(12, 12)	
		RIc:SetPoint("LEFT", self.Health, "LEFT", 4, 0)
		self.Resting = RIc
		end
		
		CIc = self.Health:CreateTexture(nil, 'OVERLAY')
		CIc:SetSize(14, 14)			
		CIc:SetPoint("LEFT", RIc, "RIGHT", 4, 0)	
		self.Combat = CIc			
		
		LIc = self.Health:CreateTexture(nil, "OVERLAY")
		LIc:SetSize(12, 12)			
		LIc:SetPoint("LEFT", CIc, "RIGHT", 4, 0)
		self.Leader = LIc
		
		MLIc = self.Health:CreateTexture(nil, 'OVERLAY')
		MLIc:SetSize(12, 12)	
		MLIc:SetPoint("LEFT", LIc, "RIGHT", 4, 0)
		self.MasterLooter = MLIc	
		
		-- plugins
		SmoothUpdate(self)
		
		-- TotemBar
		if playerClass == "SHAMAN" then		
			TotemBar(self)	
		end
		
		-- update debuff highlight
		self:RegisterEvent("UNIT_AURA", updateDispel)
		
		self:SetSize(cfg.widthP, cfg.heightP + cfg.NumbFS + cfg.PPyOffset)
	end,
		
	pClassbar = function(self, ...)
		local playerClass = select(2, UnitClass("player"))	
		
		-- plugins		
		
		if playerClass == "PALADIN" then
			self.HolyPower = CreateFrame("Frame", nil, self)
			for i = 1, 3 do
				self.HolyPower[i] = CreateFrame("StatusBar", self:GetName().."_Shards"..i, self)
				self.HolyPower[i]:SetHeight(cfg.ClassBarHeight)
				self.HolyPower[i]:SetWidth((cfg.widthCB - 8) / 3)
				if (i == 1) then
					self.HolyPower[i]:SetPoint("TOPLEFT", self, "BOTTOMLEFT", 0, 10)
				else
					self.HolyPower[i]:SetPoint("TOPLEFT", self.HolyPower[i-1], "TOPRIGHT", 4, 0)
				end
				self.HolyPower[i]:SetStatusBarTexture(cfg.tex)
				local color = self.colors.power["HOLY_POWER"]
				self.HolyPower[i]:SetStatusBarColor(color[1], color[2], color[3])

				self.HolyPowerBorder = CreateFrame("Frame", nil, self)
				self.HolyPowerBorder:SetPoint("TOPLEFT", self.HolyPower[i], "TOPLEFT", -4, 4)
				self.HolyPowerBorder:SetPoint("BOTTOMRIGHT", self.HolyPower[i], "BOTTOMRIGHT", 4, -4)					
				self.HolyPowerBorder:SetBackdrop{edgeFile = cfg.glowtex1, edgeSize = cfg.edgesize, insets = {left = cfg.insets, right = cfg.insets, top = cfg.insets, bottom = cfg.insets}}
				self.HolyPowerBorder:SetBackdropColor(0, 0, 0, 0.8)
				self.HolyPowerBorder:SetBackdropBorderColor(unpack(cfg.brdcolor))	
				self.HolyPowerBorder:SetFrameLevel(0)		
			end
		end
		
		if playerClass == "WARLOCK" then
			self.SoulShards = CreateFrame("Frame", nil, self)
			for i = 1, 3 do
				self.SoulShards[i] = CreateFrame("StatusBar", self:GetName().."_Shards"..i, self)
				self.SoulShards[i]:SetHeight(cfg.ClassBarHeight)
				self.SoulShards[i]:SetWidth((cfg.widthCB - 8) / 3)
				if (i == 1) then
					self.SoulShards[i]:SetPoint("TOPLEFT", self, "BOTTOMLEFT", 0, 10)
				else
					self.SoulShards[i]:SetPoint("TOPLEFT", self.SoulShards[i-1], "TOPRIGHT", 4, 0)
				end
				self.SoulShards[i]:SetStatusBarTexture(cfg.tex)

				local color = self.colors.power["SOUL_SHARDS"]
				self.SoulShards[i]:SetStatusBarColor(color[1], color[2], color[3])

				self.SoulShardsBorder = CreateFrame("Frame", nil, self)
				self.SoulShardsBorder:SetPoint("TOPLEFT", self.SoulShards[i], "TOPLEFT", -4, 4)
				self.SoulShardsBorder:SetPoint("BOTTOMRIGHT", self.SoulShards[i], "BOTTOMRIGHT", 4, -4)					
				self.SoulShardsBorder:SetBackdrop{edgeFile = cfg.glowtex1, edgeSize = cfg.edgesize, insets = {left = cfg.insets, right = cfg.insets, top = cfg.insets, bottom = cfg.insets}}
				self.SoulShardsBorder:SetBackdropColor(0, 0, 0, 0.8)
				self.SoulShardsBorder:SetBackdropBorderColor(unpack(cfg.brdcolor))
				self.SoulShardsBorder:SetFrameLevel(0)	
			end
		end			
			
		if playerClass =="DEATHKNIGHT" then	
			self.Runes = CreateFrame("Frame", nil, self)
			for i = 1, 6 do
				self.Runes[i] = CreateFrame("StatusBar", self:GetName().."_Runes"..i, self)
				self.Runes[i]:SetHeight(cfg.ClassBarHeight)
				self.Runes[i]:SetWidth((cfg.widthCB - 15) / 6)
				if (i == 1) then
					self.Runes[i]:SetPoint("TOPLEFT", self, "BOTTOMLEFT", 0, 10)
				else
					self.Runes[i]:SetPoint("TOPLEFT", self.Runes[i-1], "TOPRIGHT", 3, 0)
				end
				self.Runes[i]:SetStatusBarTexture(cfg.tex)

				self.Runes[i].bg = self.Runes[i]:CreateTexture(nil, "BORDER")
				self.Runes[i].bg:SetPoint("TOPLEFT", self.Runes[i], "TOPLEFT", -0, 0)
				self.Runes[i].bg:SetPoint("BOTTOMRIGHT", self.Runes[i], "BOTTOMRIGHT", 0, -0)				
				self.Runes[i].bg:SetTexture(cfg.tex)
				self.Runes[i].bg.multiplier = 0.34
				
				self.RunesBorder = CreateFrame("Frame", nil, self)
				self.RunesBorder:SetPoint("TOPLEFT", self.Runes[i], "TOPLEFT", -4, 4)
				self.RunesBorder:SetPoint("BOTTOMRIGHT", self.Runes[i], "BOTTOMRIGHT", 4, -4)						
				self.RunesBorder:SetBackdrop{edgeFile = cfg.glowtex1, edgeSize = cfg.edgesize, insets = {left = cfg.insets, right = cfg.insets, top = cfg.insets, bottom = cfg.insets}}
				self.RunesBorder:SetBackdropColor(0, 0, 0, 0.8)
				self.RunesBorder:SetBackdropBorderColor(unpack(cfg.brdcolor))	
				self.RunesBorder:SetFrameLevel(0)	
			end
		end		
		
		if playerClass == 'DRUID' and cfg.useeclip then
			local eclipseBar = CreateFrame('Frame', nil, self)
			eclipseBar:SetPoint('TOPLEFT', self, 'BOTTOMLEFT', 0, 0)
			eclipseBar:SetSize(cfg.widthCB, cfg.ClassBarHeight)
			
			eclipseBar.Border = CreateFrame("Frame", nil, self)
			eclipseBar.Border:SetPoint("TOPLEFT", eclipseBar, "TOPLEFT", -4, 4)
			eclipseBar.Border:SetPoint("BOTTOMRIGHT", eclipseBar, "BOTTOMRIGHT", 4, -4)					
			eclipseBar.Border:SetBackdrop{edgeFile = cfg.glowtex1, edgeSize = cfg.edgesize, insets = {left = cfg.insets, right = cfg.insets, top = cfg.insets, bottom = cfg.insets}}
			eclipseBar.Border:SetBackdropColor(0, 0, 0, 0.8)
			eclipseBar.Border:SetBackdropBorderColor(unpack(cfg.brdcolor))		
			eclipseBar.Border:SetFrameLevel(0)				

			local lunarBar = CreateFrame('StatusBar', nil, eclipseBar)
			lunarBar:SetPoint('LEFT', eclipseBar, 'LEFT', 0, 0)
			lunarBar:SetSize(cfg.widthCB, cfg.ClassBarHeight)
			lunarBar:SetStatusBarTexture(cfg.tex)
			lunarBar:SetStatusBarColor(0.34, 0.1, 0.86)
			eclipseBar.LunarBar = lunarBar
	
			local solarBar = CreateFrame('StatusBar', nil, eclipseBar)
			solarBar:SetPoint('LEFT', lunarBar:GetStatusBarTexture(), 'RIGHT', 0, 0)
			solarBar:SetSize(cfg.widthCB, cfg.ClassBarHeight)
			solarBar:SetStatusBarTexture(cfg.tex)
			solarBar:SetStatusBarColor(0.95, 0.73, 0.15)
			eclipseBar.SolarBar = solarBar
	
			local eclipseBarText = solarBar:CreateFontString(nil, 'OVERLAY')
			eclipseBarText:SetPoint('CENTER', eclipseBar, 'CENTER', 0, 0)
			eclipseBarText:SetFont(cfg.NumbFont, cfg.NumbFS, cfg.fontFNum)
			self:Tag(eclipseBarText, '[pereclipse]%')
		
			self.EclipseBar = eclipseBar
		end		

		self:SetSize(cfg.widthCB, cfg.heightCB)
	end,	
	
	target = function(self, ...)
		Shared(self, ...)
		self.Health:SetHeight(cfg.heightT)
		self.Health:SetWidth(cfg.widthT)	
		self.Power:SetWidth(cfg.widthT)	
		
		if cfg.useCastbar then	
		createCastbar(self)	
		self.Castbar.Text:SetPoint("LEFT", self.Castbar, "LEFT", 4, 0)	
		self.Castbar.Time2:SetPoint("RIGHT", self.Castbar, "RIGHT", -2, 0)
		self.Castbar.Time:SetPoint("RIGHT", self.Castbar.Time2, "LEFT", 0, 0)
		if cfg.movecb == true then
		self.Castbar:SetPoint(cfg.anchor, cfg.cbtp, cfg.anchor2, cfg.xpost, cfg.ypost)
		self.Castbar:SetHeight(cfg.ctheight)
		self.Castbar:SetWidth(cfg.ctwidth)
		else
		self.Castbar:SetAllPoints(self.Health)
		end
		end
		
		self.Health.value:SetPoint("LEFT", self.Health, "LEFT", 1, 8, cfg.targetHPy)		
		self.Name:SetPoint("TOPRIGHT", self.Health, "TOPRIGHT", 0, 0, cfg.NameFS+2)		
		self.Power.value:SetPoint("LEFT", self.Health, "LEFT", 4, -12)
		self.Health.value:SetFont(cfg.NumbFont, cfg.NumbFS1, cfg.fontFNum)
		self.Power.value:SetFont(cfg.NumbFont, cfg.NumbFS2, cfg.fontFNum)

		if cfg.tPervalue then
		self.Health.Text = self.Health:CreateFontString(nil, 'OVERLAY') 
		self.Health.Text:SetFont(cfg.NumbFont, cfg.NameFS, cfg.FontF)
		self.Health.Text.frequentUpdates = FreqUpdate
		self:Tag(self.Health.Text,'[smartlevel] [My_PerHP]|r')
		self.Health.Text:SetJustifyH('CENTER')
		self.Health.Text:SetTextColor(unpack(cfg.sndcolor))
		self.Health.Text:SetPoint('RIGHT',self.Health, 0, -8)	
		end
		
		-- combo point font string
		local cpoints = self.Health:CreateFontString(nil, 'OVERLAY')
		cpoints:SetPoint("RIGHT", self.Health, "RIGHT", cfg.xcombo, cfg.ycombo)
		cpoints:SetFont(cfg.NumbFont, cfg.NumbFS+cfg.combonf, cfg.fontFNum)
		cpoints:SetTextColor(unpack(cfg.sndcolor))
		self:Tag(cpoints, '[cpoints]')

		if cfg.usetb then
		createBuffs(self)	
		self.Buffs:SetPoint("TOP", self.Health, "BOTTOM", 0, -6)
		self.Buffs.initialAnchor = "TOPLEFT"	
		self.Buffs["growth-x"] = "RIGHT"		
		self.Buffs["growth-y"] = "DOWN"
		self.Buffs.size = ((cfg.widthT/8)/1.5)
		self.Buffs.num = 10
		end
		
		if cfg.usetdb then
		createDebuffs(self)
		self.Debuffs:SetPoint("TOP", self.Health, "TOP", 0, 26)
		self.Debuffs.initialAnchor = "TOPLEFT"
		self.Debuffs["growth-x"] = "RIGHT"		
		self.Debuffs["growth-y"] = "UP"
		self.Debuffs.size = ((cfg.widthT/8)/1.5)
		self.Debuffs.num = 20
		end
		
		if cfg.usePortrait then		
			createPortraits(self)
			self.Portrait:SetPoint("TOPLEFT", self, "TOPLEFT", 0, 0)
			self.Portrait.PostUpdate = Portrait_PostUpdate		
		end		
		
		if cfg.onlyShowPlayerBuffs then
			self.Buffs.onlyShowPlayer = true
		end	
		
		if cfg.onlyShowPlayerDebuffs then
			self.Debuffs.onlyShowPlayer = true
		end	
		
		-- plugins
		SpellRange(self)
		SmoothUpdate(self)
		
		-- Icons
		createRaidIcon(self)
		createQuestIcon(self)
		createPhaseIcon(self)		
		self.RaidIcon:SetPoint("CENTER", self.Health, "CENTER", 0, 0)		
		self.QuestIcon:SetPoint("LEFT", self.RaidIcon, "RIGHT", 4, 0)	
		self.PhaseIcon:SetPoint("LEFT", self.QuestIcon, "RIGHT", 4, 0)
		
		-- update debuff highlight
		self:RegisterEvent("UNIT_AURA", updateDispel)	

		self:SetSize(cfg.widthT, cfg.heightT + cfg.NumbFS + cfg.PPyOffset)
	end,
	
	focus = function(self, ...)
		Shared(self, ...)
		self.Health:SetHeight(cfg.heightF)
		self.Health:SetWidth(cfg.widthF)	
		self.Power:SetWidth(cfg.widthF)	
		self:Tag(self.Name, '[raidcolor][abbrevname]')
		
		if cfg.useCastbar then	
			createCastbar(self)			
			self.Castbar:SetAllPoints(self.Health)
			self.Castbar.Text:SetPoint("LEFT", self.Health, "LEFT", 4, 0)	
			self.Castbar.Time2:SetPoint("RIGHT", self.Castbar, "RIGHT", -2, 0)
			self.Castbar.Time:SetPoint("RIGHT", self.Castbar.Time2, "LEFT", 0, 0)
		end
		
		self.Health.value:SetPoint("RIGHT", self.Health, "RIGHT", -4, 0)					
		self.Status:SetPoint("LEFT", self.Health, "LEFT", 2, 0)
		self.Name:SetPoint("LEFT", self.Status, "RIGHT", 2, 0)
				
		createBuffs(self)	
		self.Buffs:SetPoint("TOP", self.Power, "BOTTOM", 0, -5)
		self.Buffs.initialAnchor = "TOPLEFT"	
		self.Buffs["growth-x"] = "RIGHT"		
		self.Buffs["growth-y"] = "DOWN"
		self.Buffs.size = (cfg.widthF/8)	
		self.Buffs.num = 0
		
		createDebuffs(self)
		self.Debuffs:SetPoint("BOTTOM", self.Health, "TOP", 0, 5)
		self.Debuffs.initialAnchor = "BOTTOMLEFT"
		self.Debuffs["growth-x"] = "RIGHT"		
		self.Debuffs["growth-y"] = "UP"	
		self.Debuffs.size = (cfg.widthF/8)		
		self.Debuffs.num = 0
		
		if cfg.usePortrait then		
			createPortraits(self)	
			self.Portrait:SetPoint("TOPLEFT", self, "TOPLEFT", 0, 0)		
			self.Portrait.PostUpdate = Portrait_PostUpdate		
		end
		
		if cfg.oSPlayerBuffs then
			self.Buffs.onlyShowPlayer = true
		end	
		
		if cfg.oSPlayerDebuffs then
			self.Debuffs.onlyShowPlayer = true
		end	
		
		-- plugins
		SpellRange(self)
		SmoothUpdate(self)
		
		-- Icons
		createRaidIcon(self)
		createQuestIcon(self)
		self.RaidIcon:SetPoint("CENTER", self.Health, "CENTER", 0, 0)		
		self.QuestIcon:SetPoint("LEFT", self.RaidIcon, "RIGHT", 4, 0)		
	
		-- update and debuff highlight
		self:RegisterEvent("UNIT_AURA", updateDispel)
		
		self:SetSize(cfg.widthF, cfg.heightF + cfg.NumbFS + cfg.PPyOffset)
	end,	

	pet = function(self, ...)
		Shared(self, ...)
		
		self.Health:SetHeight(cfg.heightS)
		self.Health:SetWidth(cfg.widthS)			
		self.Power:SetWidth(cfg.widthS)
		self.Name:SetPoint("CENTER", self.Health, 0, 0)
		self:Tag(self.Name, '[raidcolor][name]')		
		
		self.Power.colorPower = true				
		
		if cfg.usePortrait then		
			createPortraits(self)	
			self.Portrait:SetPoint("TOPLEFT", self, "TOPLEFT", 0, 0)		
			self.Portrait.PostUpdate = Portrait_PostUpdate		
		end
		
		-- plugins
		SpellRange(self)	

		-- Icons
		createRaidIcon(self)
		self.RaidIcon:SetPoint("CENTER", self.Health, "CENTER", 0, 0)	
		
		-- update and debuff highlight
		self:RegisterEvent("UNIT_AURA", updateDispel)
		
		self:SetSize(cfg.widthS, cfg.heightS + cfg.NumbFS + cfg.PPyOffset)
	end,
	
	targettarget = function(self, ...)
		Shared(self, ...)	

		self.Health:SetHeight(cfg.heightS)
		self.Health:SetWidth(cfg.widthS)			
		self.Power:SetWidth(cfg.widthS)	
		self.Name:SetPoint("CENTER", self.Health, "CENTER", 0, 0)
		self:Tag(self.Name, '[raidcolor][shortname]')
		
		if cfg.usePortrait then		
			createPortraits(self)	
			self.Portrait:SetPoint("TOPLEFT", self, "TOPLEFT", 0, 0)		
			self.Portrait.PostUpdate = Portrait_PostUpdate		
		end
		
		-- plugins
		SpellRange(self)
		
		-- Icons
		createRaidIcon(self)
		self.RaidIcon:SetPoint("CENTER", self.Health, "CENTER", 0, 0)		
		
		-- update and debuff highlight
		self:RegisterEvent("UNIT_AURA", updateDispel)		
		
		self:SetSize(cfg.widthS, cfg.heightS + cfg.NumbFS + cfg.PPyOffset)
	end,

	focustarget = function(self, ...)
		Shared(self, ...)
		
		self.Health:SetHeight(cfg.heightS)
		self.Health:SetWidth(cfg.widthS)			
		self.Power:SetWidth(cfg.widthS)		
		self.Name:SetPoint("CENTER", self.Health, 0, 0)	
		self:Tag(self.Name, '[raidcolor][shortname]')
		
		-- plugins
		SpellRange(self)
		
		-- Icons
		createRaidIcon(self)
		self.RaidIcon:SetPoint("CENTER", self.Health, "CENTER", 0, 0)	
		
		-- update and debuff highlight
		self:RegisterEvent("UNIT_AURA", updateDispel)		
		
		self:SetSize(cfg.widthS, cfg.heightS + cfg.NumbFS + cfg.PPyOffset)
	end,

	boss = function(self, ...)
		Shared(self, ...)
		
		self.Health:SetHeight(cfg.heightM)
		self.Health:SetWidth(cfg.widthM)				
		self.Power:SetWidth(cfg.widthM)	
		self.Name:SetPoint("RIGHT", self.Health, "RIGHT", -2, 18)
		self.Health.value:SetPoint("RIGHT", self.Health, "RIGHT", -4, 0)
		self.Power:Hide()

		if cfg.bPervalue then
		self.Health.Text = self.Health:CreateFontString(nil, 'OVERLAY') 
		self.Health.Text:SetFont(cfg.NumbFont, cfg.NameFS, cfg.FontF)
		self.Health.Text.frequentUpdates = FreqUpdate
		self:Tag(self.Health.Text,'[My_PerHP]|r')
		self.Health.Text:SetJustifyH('CENTER')
		self.Health.Text:SetTextColor(unpack(cfg.sndcolor))
		self.Health.Text:SetPoint('LEFT',self.Health, 2, 0)
		end
		
		self:Tag(self.Name, '[afkdnd][raidcolor][shortname]')		

		if cfg.usePortrait then		
			createPortraits(self)	
			self.Portrait:SetPoint("TOPLEFT", self, "TOPLEFT", 0, 0)		
			self.Portrait.PostUpdate = Portrait_PostUpdate		
		end
		
		-- plugins
		SpellRange(self)
		
		-- Icons
		createRaidIcon(self)
		self.RaidIcon:SetPoint("CENTER", self.Health, "CENTER", 0, 0)		
		
		self:SetSize(cfg.widthM, cfg.heightM + cfg.NumbFS + cfg.PPyOffset)
	end,
	
	MainTank = function(self, ...)
		Shared(self, ...)
		
		self.Health:SetHeight(cfg.heightM)
		self.Health:SetWidth(cfg.widthM)				
		self.Power:Hide()
		self.Name:SetPoint("LEFT", self.Health, "LEFT", 4, 0)
		self.Health.value:SetPoint("RIGHT", self.Health, "RIGHT", -4, 0)		

		self:Tag(self.Name, '[afkdnd][raidcolor][shortname]')	

		-- plugins
		SpellRange(self)
		
		-- Icons
		createRaidIcon(self)
		self.RaidIcon:SetPoint("CENTER", self.Health, "CENTER", 0, 0)	
	end,			
}

-- raid, party
do
	local range = {
		insideAlpha = 1,
		outsideAlpha = cfg.FadeOutAlpha,
	}
		
	UnitSpecific.raid = function(self, ...)
		Shared(self, ...)
				
		if cfg.HidePower then
		self.Power:Hide()
		self.Name:SetPoint("CENTER", self.Health, "CENTER", 0, 0)
		else
		self.Name:SetPoint("CENTER", self.Health, "CENTER", 0, 2)
		end
		self.Name:SetFont(cfg.NameFont, cfg.NameFS-3, cfg.FontF)
		self:Tag(self.Name, '[raidcolor][raidhpname]')		
		self.Health:SetHeight(cfg.heightR)
		self.Health:SetWidth(cfg.widthR)	
		self.Power:SetWidth(cfg.widthR)
		self:SetScale(cfg.rscale)
		self.Glow.pp:Hide()
		self.Power:SetHeight(5)
		self.Power:SetPoint("TOPLEFT", self.Health, "BOTTOMLEFT", 0, 5)
		self.Power:SetFrameLevel(19)
		
		-- plugins
		self.Range = range
		
		-- Icons
		createRaidIcon(self)
		self.RaidIcon:SetPoint("LEFT", self.Health, 0, 0)	
		
		rChk = self.Health:CreateTexture(nil, 'OVERLAY')
		rChk:SetSize(18, 18)
		rChk:SetPoint("RIGHT", self.Health, 0, 0)		
		rChk.fadeTimer = 6
		self.ReadyCheck = rChk
		
		-- update and debuff highlight
		self:RegisterEvent("UNIT_AURA", updateDispel)
	end
end	 
 
---------------------------------------
-- register style(s) and spawn units --
---------------------------------------
 oUF:RegisterStyle("Arp", Shared)

for unit,layout in next, UnitSpecific do
	oUF:RegisterStyle('Arp - ' .. unit:gsub("^%l", string.upper), layout)
end

local spawnHelper = function(self, unit, ...)
	if(UnitSpecific[unit]) then
		self:SetActiveStyle('Arp - ' .. unit:gsub("^%l", string.upper))
		local object = self:Spawn(unit)
		object:SetPoint(...)
		return object
	else
		self:SetActiveStyle'Arp'
		local object = self:Spawn(unit)
		object:SetPoint(...)
		return object
	end
end

oUF:Factory(function(self)
	
	local player = spawnHelper(self, 'player', "BOTTOM", -300, 260)
	if cfg.useClassBar and playerClass == "WARLOCK" or playerClass == "DEATHKNIGHT" or playerClass == "PALADIN" then
	spawnHelper(self, 'pet', "BOTTOM", player, "BOTTOM", -(cfg.widthP/2-cfg.widthS/2), -(cfg.heightS+cfg.playerHPy*3+cfg.heightPP+cfg.ClassBarHeight))
	else
	spawnHelper(self, 'pet', "BOTTOM", player, "BOTTOM", -(cfg.widthP/2-cfg.widthS/2), -(cfg.heightS+cfg.playerHPy*2+cfg.heightPP))
	end
	local target = spawnHelper(self, 'target', "BOTTOM", 290, 260)
	local targettarget = spawnHelper(self, 'targettarget', "BOTTOM", 0, 260)
	local focus = spawnHelper(self, 'focus', "BOTTOMLEFT", 320, 300)
	spawnHelper(self, 'focustarget', "CENTER", focus, "TOP", 0, 15)
		
if cfg.RaidandParty then	
CompactRaidFrameManager:UnregisterAllEvents()
CompactRaidFrameManager:Hide()
CompactRaidFrameContainer:UnregisterAllEvents()
CompactRaidFrameContainer:Hide()	
	
	self:SetActiveStyle"Arp - Raid"
	local raid = self:SpawnHeader('oUF_Raid', nil, 'solo,party,raid,raid10,raid25,raid40',	
	'showParty', true,
	'showRaid', true, 
	'showPlayer', true,
	'groupFilter', '1,2,3,4,5,6,7,8',
	'groupingOrder', '1,2,3,4,5,6,7,8',
	'groupBy', 'GROUP',
	'maxColumns', cfg.columns,
	'unitsPerColumn', 5,
	'column', 4,
	'columnAnchorPoint', "TOP",
	'columnSpacing', cfg.groupspace,
	'yoffset', 20,
	'xoffset', 6,
	'point', 'LEFT',
	'oUF-initialConfigFunction', ([[
			self:SetWidth(%d)
			self:SetHeight(%d)
    ]]):format(cfg.widthR, cfg.heightR + cfg.NumbFS + cfg.PPyOffset))
	--raid:SetPoint("BOTTOM", UIParent, "BOTTOM", 0, 150)	
	raid:SetPoint("TOPLEFT", UIParent, "TOPLEFT", cfg.raidxpos, cfg.raidypos)	
end

if cfg.BossFrames then		
	self:SetActiveStyle"Arp - Boss"
	local boss = {}
		for i = 1, MAX_BOSS_FRAMES do
			local unit = self:Spawn("boss"..i, "oUF_ArpBoss"..i)

			if i==1 then
				unit:SetPoint("TOPRIGHT", UIParent, "TOPRIGHT", cfg.bxpos, cfg.bypos)
			else
				unit:SetPoint("TOPLEFT", boss[i-1], "BOTTOMLEFT", 0, -10)
			end
			boss[i] = unit
		end
end
		
if cfg.MTFrames then		
	self:SetActiveStyle"Arp - MainTank"
	local Main_Tank = self:SpawnHeader("oUF_MainTank", nil, 'raid, party, solo', 
		'showRaid', true, 
		"groupFilter", "MAINTANK", 
		'yOffset', -8, 
		"template", "oUF_ArpMTartemplate",		-- MT Target
		'oUF-initialConfigFunction', ([[
			self:SetWidth(%d)
			self:SetHeight(%d)
		]]):format(cfg.widthM, cfg.heightM))		
	Main_Tank:SetPoint("TOPRIGHT", UIParent, "TOPRIGHT", -80, -250)		
end
	
if cfg.useClassBar then 
if playerClass == "WARLOCK" or playerClass == "PALADIN" or playerClass == "DEATHKNIGHT" or playerClass == "DRUID" then	
	oUF:RegisterStyle("oUF_Arp_pClassbar", UnitSpecific.pClassbar)
	oUF:SetActiveStyle("oUF_Arp_pClassbar")
	oUF:Spawn('player', 'pClassbar'):SetPoint("BOTTOM", player, "BOTTOM", 0, -cfg.PPyOffset)
end
end
end)

-- remove SET_FOCUS & CLEAR_FOCUS from menu, to prevent errors
do 
    for k,v in pairs(UnitPopupMenus) do
        for x,y in pairs(UnitPopupMenus[k]) do
            if y == "SET_FOCUS" then
                table.remove(UnitPopupMenus[k],x)
            elseif y == "CLEAR_FOCUS" then
                table.remove(UnitPopupMenus[k],x)
            end
        end
    end
end

-------------
-- The End --
-------------